# Практика avm, примеры интерфейсов В данном разделе будет расписана некоторая практика, связанная с разметкой в avm. Будут рассмотрены различные реализации интерфейсов. ## Присоединение нескольких отображений (одновременно с закладками и без) ![](img/avm-Example_avm_1.jpg) Для этого в разметке нужно выбрать tabDynamicComposer, который позволяет присоединять, как с помощью dynamicItems, так и с помощью tabItems. ```{note} Напомню, что: - dynamicItems - обычное присоединение отображения с возможность выбора выравнивания; - tabItems - присоединение отображения, как вкладка. ``` ```xml ``` ```{note} В примере разметки в tabItems присоединены вкладки, настроенные на типе объекта. Это часто встречающаяся практика, данный пример полезно понимать. ``` ## Как убрать кнопку сворачивания отображения в модальное окно Чтобы убрать кнопку сворачивания отображения, присоединенного dynamicItems, ![](img/avm-collapsingModalWin.jpg) необходимо выключить header у frame: ```xml ``` Таким способом будет убран заголовок с кнопкой. Заголовок можно вернуть с помощью конструкции `vGroup`. ```xml ``` Отображение с кнопкой сворачивания: ![](img/avm-headerVisibleTrue.jpg) Отображение с выключенным header: ![](img/avm-headerVisibleFalse.jpg) Отображение с vGroup: ![](img/avm-headerVisibleFalseVGroup.jpg) ## Динамическая смена отображения Эта тема отвечает на вопрос, как при изменении значения поля менять присоединяемое отображение. ```{note} Так работает tabItems на типе объекта: при смене типа объекта набор вкладок в tabItems меняется на те, которые настроены на выбранном типе объекта. ``` ### Смена отображений при изменении значения фильтра Пример реализации: `ru.bitec.app.oil.Oil_TaskMonitor.avm.xml` - разметка отображения `Card`, `ru.bitec.app.oil.Oil_TaskMonitorAvi.Card` - результат выборки отображения `Card`. avm: ```xml ``` Это отображение Card. В тэге `filter` определены фильтры. Панель фильтров включена свойством тэга ``. Присоединение отображений выполнено инструментом `tabDynDetComposer`, который позволяет присоединять как `tabItems` (закладками), так и `dynDetail` (аналогия `dynamicItem`). Закладка `tabItems` присоединена, как пустышка, чтобы заработал `tabDynDetComposer` (проблема была актуальна на 05.07.2023, обещали исправить). В закладке `dynDetail` определены свойства, значения которых являются атрибутами отображения (см. перечень атрибутов отображения). Тем самым отображение `Card`, как результат выборки должно иметь настройку для `dynDetail`. Для формирования такой выборки необходимо рассмотреть Avi: ```scala trait List_CommonResource extends Default with List_CoreResource { override protected val sNameFieldForGST = "Brigade" override protected val sNameTableForGST = "Bs_Brigade" } trait Card extends Default with super.Card { //Типы объекта класса Oil_Task и соответствующие отображения к ним lazy val mapRepByOT: Map[NString, NString] = Map("Oil_TaskReceive".ns -> "List_RecievTask".ns , "Oil_TaskShip".ns -> "List_ShipTask".ns , "Oil_TaskCommon".ns -> "List_CommonTask".ns ) @FlushBefore(mode = FlushBeforeMode.Disabled) override protected def onRefresh: Recs = { val idvOT = getVar("flt_idObjectType").asNLong if (idvOT.isNotNull) { val sRep = mapRepByOT.getOrElse(Btk_ObjectTypeApi().getMnemoCode(idvOT), throw AppException("Не найдено отображение.")) s""" select 'gtk-Oil_TaskMonitorAvi' as sSelectionAttr ,'$sRep' as sRepresentationAttr ,'${Btk_ObjectTypeApi().getShortCaption(idvOT)}' as sCaptionAttr ,cast(null as numeric) as nImageIndexAttr ,'{}' as jsonParams """ } else { s""" select cast(null as int8) as id ,cast(null as numeric) as nOrder ,cast(null as varchar) as sCaptionAttr ,cast(null as numeric) as nImageIndexAttr ,cast(null as varchar) as sRepresentationAttr ,cast(null as varchar) as sSelectionAttr ,'{}' as jsonParams where false """ } } override protected def selectStatement: JClob = s"" } ``` У отоборажения есть фильтр по типу объекта `flt_idObjectType` с редактором `lookup`. При выборе различных типов объекта к `Card` должны присоединяться различные отображения (их соответствие описано в Map `mapRepByOT`). Алгоритм метода `onRefresh`: - Проверка, не пустое ли значение фильтра типа объекта ```scala val idvOT = getVar("flt_idObjectType").asNLong if (idvOT.isNotNull) ``` - Получение соответствующего отображения для выбранного типа объекта из `mapRepByOT`: ```scala val sRep = mapRepByOT.getOrElse(Btk_ObjectTypeApi().getMnemoCode(idvOT), throw AppException("...")) ``` - Формирование выборки: `sSelectionAttr` - выборка, отображение которого присоединяется (в рассматриваемом случае все отображения принадлежат одной и той же выборке); `sRepresentationAttr` - соответствующее отображение `sCaptionAttr` - описание отображения `nImageIndexAttr` - картинка отображения `jsonParams` - json параметры ### Смена отображений при изменении значения поля отображения Если нужно менять отображения в зависимости от значения полей отображения `Card`, то нужно сделать промежуточное отображение с механикой, описанной выше (например, `List_Tab`), которое присоединить к `Card`. ## Фиксация ширины столбца/поля и задание значения ширины В карточке: Необходимо для атрибута задать свойства в тэге `card`: ```xml ``` В списке: Необходимо для атрибута задать свойства в тэге `grid`: ```xml ``` `controlWidth` - ширина поля `isControlWidthFixed` - true - ширина будет зафиксирована, false - доступна для редактирования в интерфейсе. ## Убрать описание у поля Чтобы убрать заголовок у поля, писать `` неправильно. Необходимо задать свойство `labelPosition`: ```xml ``` Помимо значения `"none"` свойство `labelPosition` имееть значения: - `"right"` - справа - `"left"` - слева - `"above"` - сверху - `"under"` - снизу ## Как в списке покрасить ячейку Для этого необходимо иметь дополнительный атрибут, в который будет записываться системное имя стиля. Обычно такой атрибут называют `sStyle`. Далее необходимо указать, что столбец такого-то атрибута имеет стиль, описанный в атрибуте `sStyle`: ```xml